package com.example.serialportdemo.service;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

import com.example.serialportdemo.IMyAidlInterface;
import com.example.serialportdemo.vaccine;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import android_serialport_api.ComPort;

import static com.example.serialportdemo.Func.getX1X2;
import static com.example.serialportdemo.Func.toUnsigned;
import static com.example.serialportdemo.vaccine.CommSendCmd;

public class SerialPortService extends Service {
    final ComPort com = new ComPort();
    private float temperature,targetTemperature;
    private boolean[] lockstate;//开门：true  关门：false
    private boolean[] warn;//警告：true    正常：false
    private Lock locker = new ReentrantLock();
    private Condition waiter = locker.newCondition();
    private final int timeout = 200;
    boolean test_flag,reset_flag;//true:成功   false:失败
    byte test_mode;//0x00:制冷系统1   0x01：制冷系统2

    public SerialPortService() {
    }
    public void initSerialport(){
        boolean bOpen = com.open("/dev/ttyS4", 9600, new ComPort.DataHandler() {
            @Override
            public void onDataReceived(String comName, byte[] buffer, int size) {
                if (mHandler != null) {
                    if (vaccine.check_recvData(buffer, size)) {
                        Message msg = Message.obtain();
                        msg.obj = buffer;
                        msg.arg1 = size;
                        switch (buffer[4]) {
                            case (byte) 0x91:
                                msg.what = 1;
                                break;
                            case (byte) 0xB1:
                                msg.what = 2;
                                break;
                            case (byte) 0xB4:
                                msg.what = 3;
                                break;
                            case (byte) 0xE8:
                                msg.what = 4;
                                break;
                            case (byte) 0xE1:
                                msg.what = 5;
                                break;
                            case (byte) 0xCE:
                                msg.what = 6;
                                break;
                        }
                        mHandler.sendMessage(msg);
                    }
                }
            }
        });
        if (bOpen) {
            Log.i("串口打开", "成功");
        } else {
            Log.e("串口打开", "失败");
        }
    }
    IMyAidlInterface.Stub mBind=new IMyAidlInterface.Stub() {
        @Override
        public boolean unlockCabinet(int cabinet) throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x02,1,new byte[]{(byte)cabinet});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return true;
        }

        @Override
        public boolean[] isCabinetUnlock() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x11,1,new byte[]{(byte)0X01});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return lockstate;
        }

        @Override
        public boolean setTargetTemperature(float s) throws RemoteException {
            byte[] data=CommSendCmd((byte) 0x21,6,new byte[]{getX1X2(s)[0],getX1X2(s)[1],0x0A,0x05,0x0A,0x05});
            com.sendData(data,data.length);
            return true;
        }

        @Override
        public float[] getTargetTemperature() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x31,1,new byte[]{(byte)0X01});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return new float[]{targetTemperature};
        }

        @Override
        public float[] getTemperature() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x34,1,new byte[]{(byte)0X01});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return new float[]{temperature};
        }

        @Override
        public boolean[] getWarnInfo() throws RemoteException {
            return warn;
        }

        @Override
        public boolean switchTestMode() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x68,4,new byte[]{(byte)0X01,(byte)0x80,0x02,(byte)0x90});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return test_flag;
        }

        @Override
        public boolean switchTestMode_1() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x61,1,new byte[]{0x00});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            if(test_mode==0x00){
                return true;
            }
            return false;
        }

        @Override
        public boolean switchTestMode_2() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x61,1,new byte[]{0x01});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            if(test_mode==0x01){
                return true;
            }
            return false;
        }

        @Override
        public boolean resetSystem() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x4E,1,new byte[]{0x01});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return reset_flag;
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        lockstate=new boolean[4];
        initSerialport();
        return mBind;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    public Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            byte[] data = (byte[]) msg.obj;
            int len = msg.arg1;
            switch (msg.what) {
                case 1:isCabinetUnlock_resp(data, len);
                    break;
                case 2:getTargetTemperature_resp(data,len);
                    break;
                case 3:getTemperature_resp(data,len);
                getTemperature_resp_1(data,len);
                    break;
                case 4:test_resp(data,len);
                    break;
                case 5:test_choose_resp(data,len);
                    break;
                case 6:reset_resp(data,len);
                    break;
            }
        }
    };
//    private void isCabinetUnlock_resp(byte[] data,int len,LockStateListener lockStateListener){
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                byte[] temp=data;
//                for(int i=0;i<4;i++){
//                    if(((temp[5]>>i)&0x01)==0x01){
//                        lockStateListener.isOpen();
//                    }
//                    else{
//                        lockStateListener.isClose();
//                    }
//                }
//            }
//        }).start();
//    }
//    public interface LockStateListener{
//        void isOpen();
//        void isClose();
//    }
    private boolean[] isCabinetUnlock_resp(byte[] data,int len){
        boolean[] booleans=new boolean[4];
        for(int i=0;i<4;i++){
            if(((data[5]>>i)&0x01)==0x01){
                booleans[i]=true;//开门
            }
            else{
                booleans[i]=false;//关门
            }
        }
        lockstate=booleans;
        return lockstate;
    }
    private float getTargetTemperature_resp(byte[] data,int len){
        targetTemperature=(256*data[6]+toUnsigned(data[5])-1280)/10;
        return targetTemperature;
    }
    private float getTemperature_resp(byte[] data,int len){
        temperature=(float)(256*data[6]+toUnsigned(data[5])-1280)/10;
        return temperature;
    }
    private boolean[] getTemperature_resp_1(byte[] data, int len){
        boolean[] b=new boolean[14];
        for(int i=0;i<8;i++){
            if(((data[7]>>i)&0x01)==0x01){
                b[i]=true;
            }
            else{
                b[i]=false;
            }
        }
        for(int i=0;i<6;i++){
            if(((data[8]>>i)&0x01)==0x01){
                b[8+i]=true;
            }
            else{
                b[8+i]=false;
            }
        }
        warn=b;
        return warn;
    }
    public boolean test_resp(byte[] byt,int len){
        if(byt[5]==0x01){
            test_flag=true;
        }
        else{
            test_flag=false;
        }
        return test_flag;
    }
    public byte test_choose_resp(byte[] byt,int len){
        test_mode=byt[5];
        return test_mode;
    }
    public boolean reset_resp(byte[] byt,int len){
        if(byt[5]==0x01){
            reset_flag=true;
        }
        else{
            reset_flag=false;
        }
        return reset_flag;
    }
}
